package com.manger.common.utils;

import org.apache.commons.lang.StringUtils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

/**
 * 大端：bigEndian， 小端：smallEdian
 * <p>
 * ByteBuffer.wrap(b)//大端数据  ByteBuffer:使用的数据均为大端数据，翻转byte[]获取到小端数据
 */
public class SocketByteConvertUtils {

    /**
     * int转小端4byte[]
     */
    public static byte[] smallEndianIntTo4Byte(int n) {
        byte[] b = new byte[4];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        return b;
    }

    /**
     * int转小端2byte[]
     */
    public static byte[] smallEndianIntTo1Byte(int n) {
        byte[] b = new byte[1];
        b[0] = (byte) (n & 0xff);

        return b;
    }

    /**
     * int转小端2byte[]
     */
    public static byte[] smallEndianIntTo2Byte(int n) {
        byte[] b = new byte[2];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);

        return b;
    }

    /**
     * 小端4byte转int
     */
    public static int smallEndian4ByteToInt(byte[] b) {
        int intValue = 0;
        byte[] t_byte = {0, 0, 0, 0};

        if (b.length <= 4) {
            System.arraycopy(b, 0, t_byte, 4 - b.length, b.length);
        }
        for (int i = 0; i < t_byte.length; i++) {
            intValue += (t_byte[i] & 0xFF) << (8 * (i));
        }
        return intValue;
    }

    /**
     * 小端2byte转int
     */
    public static int smallEndian2ByteToInt(byte[] b) {
        int intValue = 0;
        byte[] t_byte = {0, 0};

        if (b.length <= 2) {
            System.arraycopy(b, 0, t_byte, 2 - b.length, b.length);
        }
        for (int i = 0; i < t_byte.length; i++) {
            intValue += (t_byte[i] & 0xFF) << (8 * (i));
        }
        return intValue;
    }

    /**
     * 大端4byte转int
     */
    public static int bigEndian4ByteToInt(byte[] src) {
        int value;
        value = (int) ((src[3] & 0xFF)
                | ((src[2] & 0xFF) << 8)
                | ((src[1] & 0xFF) << 16)
                | ((src[0] & 0xFF) << 24));
        return value;
    }

    /**
     * int转大端4byte
     */
    public static byte[] bigEndianIntTo4Byte(int value) {
        byte[] src = new byte[4];
        src[3] = (byte) (value & 0xFF);
        src[2] = (byte) ((value >> 8) & 0xFF);
        src[1] = (byte) ((value >> 16) & 0xFF);
        src[0] = (byte) ((value >> 24) & 0xFF);
        return src;
    }

    /**
     * int转大端2byte
     */
    public static byte[] bigEndianIntTo1Byte(int value) {
        byte[] src = new byte[1];
        src[0] = (byte) (value & 0xFF);
        return src;
    }

    /**
     * int转大端2byte
     */
    public static byte[] bigEndianIntTo2Byte(int value) {
        byte[] src = new byte[2];
        src[1] = (byte) (value & 0xFF);
        src[0] = (byte) ((value >> 8) & 0xFF);
        return src;
    }

    /**
     * 大端1byte转int
     */
    public static int bigEndian1ByteToInt(byte src) {
        /*int value;
        value = (int) ((src & 0xFF) << 8);
        return value;*/
        return (int)src;
    }

    /**
     * 大端2byte转int
     */
    public static int bigEndian2ByteToInt(byte[] src) {
        int value;
        value = (int) ((src[1] & 0xFF)
                | ((src[0] & 0xFF) << 8));
        return value;
    }

    /**
     * long 转大端8byte
     */
    public static byte[] longTo8Byte(long value) {
        return ByteBuffer.allocate(8).putLong(value).array();
    }

    /**
     * 大端8byte转long
     */
    public static long byte8ToLong(byte[] value) {
        return ByteBuffer.wrap(value).getLong();
    }

    /**
     * float 转大端4byte，float在转换中精度胡丢失，只能保证两位小数正确
     */
    public static byte[] floatTo4Byte(float value) {
        return ByteBuffer.allocate(4).putFloat(value).array();
    }

    /**
     * 大端4byte转float，float在转换中精度胡丢失，只能保证两位小数正确
     */
    public static float byte4ToFloat(byte[] value) {
        return ByteBuffer.wrap(value).getFloat();
    }

    /**
     * short 转大端2byte
     */
    public static byte[] shortTo2Byte(short value) {
        return ByteBuffer.allocate(2).putShort(value).array();
    }

    /**
     * 大端2byte转short
     */
    public static short byte2ToShort(byte[] value) {
        return ByteBuffer.wrap(value).getShort();
    }

    /**
     * double 转大端8byte
     */
    public static byte[] doubleTo8Byte(double value) {
        return ByteBuffer.allocate(8).putDouble(value).array();
    }

    /**
     * 大端8byte转double
     */
    public static double byte8ToDouble(byte[] value) {
        return ByteBuffer.wrap(value).getDouble();
    }

    /**
     * char转大端2byte
     */
    public static byte[] charTo2Byte(char ch) {
        return ByteBuffer.allocate(2).putChar(ch).array();
    }

    /**
     * 大端2byte转char
     */
    public static char byte2Tochar(byte[] value) {
        return ByteBuffer.wrap(value).getChar();
    }

    /**
     * 大端翻转后获得小端数据
     */
    public static byte[] flipByteArray(byte[] value) {
        byte[] result = new byte[value.length];
        for (int i = 0; i < value.length; i++) {
            result[value.length - 1 - i] = value[i];
        }
        return result;
    }

    /**
     * byte[]截取
     */
    public static byte[] midByteArray(byte[] source, int startIndex, int len) {
        byte[] target = new byte[len];
        System.arraycopy(source, startIndex, target, 0, len);
        return target;
    }

    /**
     * 16进制字符串转数组
     */
    public static byte[] hexStrToByte(String hexString) {
        if (StringUtils.isEmpty(hexString)) {
            return null;
        }

        hexString = hexString.replaceAll(" ", "");
        int len = hexString.length();
        int index = 0;

        byte[] bytes = new byte[len / 2];

        while (index < len) {
            String sub = hexString.substring(index, index + 2);
            bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
            index += 2;
        }

        return bytes;
    }

    /**
     * 数组转16进制字符串
     */
    public static String bytesToHexString(byte[] bArray) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 10进制字符串转16进制字符串
     */
    public static String stringToHexString(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }

    /**
     * 16进制字符串转10进制字符串
     */
    public static String hexStringToString(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        try {
            return new String(bytes, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static void mergeByteArray(byte[] target, byte[]... scrs) {
        int len = 0;
        for (byte[] src : scrs) {
            System.arraycopy(src, 0, target, len, src.length);
            len += src.length;
        }
    }


    /**
     * byteBuffer 转 byte数组
     *
     * @param buffer
     * @return
     */
    public static byte[] bytebuffer2ByteArray(ByteBuffer buffer) {
        //重置 limit 和postion 值
        buffer.flip();
        //获取buffer中有效大小
        int len = buffer.limit() - buffer.position();

        byte[] bytes = new byte[len];

        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = buffer.get();

        }

        return bytes;
    }

    /**
     * byte 数组转byteBuffer
     *
     * @param byteArray
     */
    public static ByteBuffer byte2Buffer(byte[] byteArray) {

        //初始化一个和byte长度一样的buffer
        ByteBuffer buffer = ByteBuffer.allocate(byteArray.length);
        // 数组放到buffer中
        buffer.put(byteArray);
        //重置 limit 和postion 值 否则 buffer 读取数据不对
        buffer.flip();
        return buffer;
    }

    public static boolean[] byteToBooleanBitArray(byte b) {
        return byteArrayToBooleanBitArray(new byte[]{b});
    }

    public static int[] byteToIntBitArray(byte b) {
        return byteArrayToIntBitArray(new byte[]{b});
    }

    public static int[] byteArrayToIntBitArray(byte[] byteArray) {
        int[] bitArray = new int[byteArray.length * 8];
        for (int i = 0; i < byteArray.length; i++) {
            for (int j = 0; j < 8; j++) {
                bitArray[i * 8 + j] = ((byteArray[i] >> (7 - j)) & 1);
            }
        }
        return bitArray;
    }

    public static boolean[] byteArrayToBooleanBitArray(byte[] byteArray) {
        boolean[] bitArray = new boolean[byteArray.length * 8];
        for (int i = 0; i < byteArray.length; i++) {
            for (int j = 0; j < 8; j++) {
                bitArray[i * 8 + j] = ((byteArray[i] >> (7 - j)) & 1) == 1;
            }
        }
        return bitArray;
    }

    public static boolean[][] byteArrayTo2BooleanBitArray(byte[] byteArray) {
        boolean[][] bitArray = new boolean[byteArray.length][8];
        for (int i = 0; i < byteArray.length; i++) {
            boolean[] temp = new boolean[8];
            temp[0] = ((byteArray[i] >> 0) & 1) == 1;
            temp[1] = ((byteArray[i] >> 1) & 1) == 1;
            temp[2] = ((byteArray[i] >> 2) & 1) == 1;
            temp[3] = ((byteArray[i] >> 3) & 1) == 1;
            temp[4] = ((byteArray[i] >> 4) & 1) == 1;
            temp[5] = ((byteArray[i] >> 5) & 1) == 1;
            temp[6] = ((byteArray[i] >> 6) & 1) == 1;
            temp[7] = ((byteArray[i] >> 7) & 1) == 1;

            bitArray[i] = temp;
        }
        return bitArray;
    }

    public static int[][] byteArrayTo2IntBitArray(byte[] byteArray) {
        int[][] bitArray = new int[byteArray.length][8];
        for (int i = 0; i < byteArray.length; i++) {
            int[] temp = new int[8];
            /*for (int j = 0; j < 8; j++) {
                temp[j] = ((byteArray[i] >> (7 - j)) & 1);
            }*/

           /* int num = (bitArray[i] & 1) << 0 ;
            num+= (bitArray[i+1] & 1) << 1 ;
            num+= (bitArray[i+2] & 1) << 2 ;
            num+= (bitArray[i+3] & 1) << 3 ;
            num+= (bitArray[i+4] & 1) << 4 ;
            num+= (bitArray[i+5] & 1) << 5 ;
            num+= (bitArray[i+6] & 1) << 6 ;
            num+= (bitArray[i+7] & 1) << 7 ;*/
            bitArray[i] = temp;
        }
        return bitArray;
    }

    /*public static byte[] bitArrayIntToByteArray(int[] bitArray) {
        int byteCount = bitArray.length / 8;
        if (bitArray.length % 8 != 0) {
            byteCount++;
        }
        byte[] byteArray = new byte[byteCount];
        for (int i = 0; i < bitArray.length; i++) {
            if (bitArray[i] == 1) {
                byteArray[i / 8] |= (1 >> (7 - (i % 8)));
            }
        }
        return byteArray;
    }*/
    public static byte[] bitArrayIntToByteArray(int[] bitArray) {
        int byteCount = bitArray.length / 8;
        if (bitArray.length % 8 != 0) {
            byteCount++;
        }
        byte[] byteArray = new byte[byteCount];
        int j = 0;
        for (int i = 0; i < bitArray.length; i += 8) {
            int num = (bitArray[i] & 1) << 0;
            num += (bitArray[i + 1] & 1) << 1;
            num += (bitArray[i + 2] & 1) << 2;
            num += (bitArray[i + 3] & 1) << 3;
            num += (bitArray[i + 4] & 1) << 4;
            num += (bitArray[i + 5] & 1) << 5;
            num += (bitArray[i + 6] & 1) << 6;
            num += (bitArray[i + 7] & 1) << 7;
            byteArray[j] = SocketByteConvertUtils.bigEndianIntTo1Byte(num)[0];
        }
        return byteArray;
    }


    public static byte[] bitArrayBooleanToByteArray(boolean[] bitArray) {
        int byteCount = bitArray.length / 8;
        if (bitArray.length % 8 != 0) {
            byteCount++;
        }
        byte[] byteArray = new byte[byteCount];
        for (int i = 0; i < bitArray.length; i++) {
            if (bitArray[i]) {
                byteArray[i / 8] |= (1 << (7 - (i % 8)));
            }
        }
        return byteArray;
    }


    public static byte[] bitArray2BooleanToByteArray(boolean[][] bitArray) {
        byte[] byteArray = new byte[bitArray.length];
        for (int i = 0; i < bitArray.length; i++) {
            for (int j = 0; j < bitArray[i].length; j++) {
                if (bitArray[i][j]) {
                    byteArray[i] |= (1 << (7 - j));
                }
            }
        }
        return byteArray;
    }

    public static byte[] bitArray2IntToByteArray(boolean[][] bitArray) {
        byte[] byteArray = new byte[bitArray.length];
        for (int i = 0; i < bitArray.length; i++) {
            for (int j = 0; j < bitArray[i].length; j++) {
                if (bitArray[i][j]) {
                    byteArray[i] |= (1 << (7 - j));
                }
            }
        }
        return byteArray;
    }

    public static int[] booleanBitToIntBit(boolean[] bitArray) {
        int[] intArray = new int[bitArray.length];
        for (int i = 0; i < bitArray.length; i++) {
            intArray[i] = bitArray[i] ? 1 : 0;
        }
        return intArray;
    }

    public static int[][] booleanBitToIntBit(boolean[][] bitArray) {
        int[][] intArray = new int[bitArray.length][8];
        for (int i = 0; i < bitArray.length; i++) {
            for (int j = 0; j < 8; j++) {
                intArray[i][j] = bitArray[i][j] ? 1 : 0;
            }
        }
        return intArray;
    }

    public static void main(String[] args) throws Exception {

     /*   int[] num = {1, 1, 1, 1, 1, 1, 1, 1};
        SocketByteConvertUtils.bitArrayIntToByteArray(num);*/
        int i = 10086;
        byte[] data = SocketByteConvertUtils.bigEndianIntTo2Byte(i);
        System.out.println(SocketByteConvertUtils.bytesToHexString(data));
       /* byte[] byteArray = {0, 32}; // 示例字节数组
        boolean[] bitArray = SocketByteConvertUtils.byteArrayToBooleanBitArray(byteArray);
        for (boolean bit : bitArray) {
            System.out.print(bit ? 1 : 0);
        }
        System.out.println();
        int[] temp = SocketByteConvertUtils.byteArrayToIntBitArray(byteArray);
        for (int i : temp) {
            System.out.print(i);
        }
        System.out.println();
        byte[] bb = SocketByteConvertUtils.bitArrayIntToByteArray(temp);
        for (byte b : bb) {
            System.out.print(b + " ");
        }
        SocketByteConvertUtils.byteArrayTo2BooleanBitArray(byteArray);*/
      /*
       byte[] result = SocketByteConvertUtils.bitArrayToByteArray(bitArray);
        for (byte b : result) {
            System.out.print(b + " ");
        }
        System.out.println();
        boolean[][] booleans = SocketByteConvertUtils.byteArrayTo2BitArray(byteArray);
        for (boolean[] booleans1 : booleans) {
            for (boolean bit : booleans1) {
                System.out.print(bit ? 1 : 0);
            }
            System.out.println();
        }
        System.out.println("===========================");
        int[][] temp2 = SocketByteConvertUtils.booleanBitToIntBit(booleans);
        for(int[] is : temp2){
            for(int i : is){
                System.out.print(i);
            }
        }
        System.out.println();
        byte[] rr = SocketByteConvertUtils.bitArray2ToByteArray(booleans);
        for (byte b : rr) {
            System.out.print(b + " ");
        }
        System.out.println();
        boolean[] bitArray1 = SocketByteConvertUtils.byteToBitArray((byte)32);
        for(boolean b: bitArray1){
            System.out.print(b ? 1 : 0);
        }
        System.out.println();
        int[] temp1 = SocketByteConvertUtils.booleanBitToIntBit(bitArray1);
        for(int i : temp1){
            System.out.print(i);
        }*/
//        byte[] b = SocketByteConvertUtils.bigEndianIntTo4Byte(6);
//
//        byte[] result = SocketByteConvertUtils.flipByteArray(b);
//
//        System.out.println(SocketByteConvertUtils.smallEndian4ByteToInt(result));
//
//        System.out.println(ByteBuffer.wrap(b).getInt());
//
//        double d = 1253.1215020241d;
//
//        System.out.println(SocketByteConvertUtils.byte8ToDouble(SocketByteConvertUtils.doubleTo8Byte(d)));
//
//        short s = 122;
//
//        System.out.println(SocketByteConvertUtils.byte2ToShort(SocketByteConvertUtils.shortTo2Byte(s)));
//
//        float f = 125482.111113f;
//
//        System.out.println(SocketByteConvertUtils.byte4ToFloat(SocketByteConvertUtils.floatTo4Byte(f)));
//
//        long l = 2363022l;
//
//        System.out.println(SocketByteConvertUtils.byte8ToLong(SocketByteConvertUtils.longTo8Byte(l)));
//
//        char ch = 'A';
//
//        System.out.println(SocketByteConvertUtils.byte2Tochar(SocketByteConvertUtils.charTo2Byte(ch)));
//       byte[] data = SocketByteConvertUtils.bigEndianIntTo2Byte(5625);
//       String hexString = SocketByteConvertUtils.bytesToHexString(data);
//       byte[] hexByte = SocketByteConvertUtils.hexStrToByte(hexString);
//       byte[] bytes = hexString.getBytes("utf-8");
//        System.out.println(data.length);
//        System.out.println(hexString);
//        System.out.println(hexByte.length);
//        System.out.println(SocketByteConvertUtils.bigEndian2ByteToInt(SocketByteConvertUtils.hexStrToByte(SocketByteConvertUtils.bytesToHexString(hexByte))));
//        System.out.println("-----------------------------------");
//        int i = 356;
//        System.out.println(Integer.toHexString(i));
//        System.out.println();
        byte[] bytes = {1};
        System.out.println(SocketByteConvertUtils.bigEndian1ByteToInt(bytes[0]));
    }
}
